package com.googlecode.smartgwtmavenplugin.mojo.lifted;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.util.Collection;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.installer.ArtifactInstallationException;
import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.artifact.ProjectArtifactMetadata;
import org.apache.maven.project.validation.ModelValidationResult;
import org.apache.maven.project.validation.ModelValidator;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;


/**
 * Deploys SmartGWT runtime to a remote repository.  Adapted under the Apache 2 license from version 2.7 of the 
 * DeployFileMojo at http://maven.apache.org/plugins/maven-deploy-plugin/.  The original Author's name is preserved to give credit
 * where credit is due, but changes have been made to the original to better suit my own purpose.  Namely, this object's execute 
 * method iterate's over a collection of files, where the original operated on one file at a time keeping details of the file in 
 * member variables.
 * 
 * @author <a href="mailto:aramirez@apache.org">Allan Ramirez</a>
 * @goal deploy
 * @execute goal=install
 * @requiresProject false
 */
public class DeployMojo extends AbstractDeployMojo {

	/** @parameter property="workdir.unpacked" */
	private File unpacked;

	/**
	 * The component used to validate the user-supplied artifact coordinates.
	 * 
	 * @component
	 */
	private ModelValidator modelValidator;

	/**
	 * Server Id to map on the &lt;id&gt; under &lt;server&gt; section of
	 * settings.xml In most cases, this parameter will be required for
	 * authentication.
	 * 
	 * @parameter property="repository.id" default-value="remote-repository"
	 * @required
	 */
	private String repositoryId;

	/**
	 * URL where the artifact will be deployed. <br/>
	 * ie ( file:///C:/m2-repo or scp://host.com/path/to/repo )
	 * 
	 * @parameter property="repository.url"
	 * @required
	 */
	private String repositoryUrl;

	/**
	 * The type of remote repository layout to deploy to. Try <i>legacy</i> for
	 * a Maven 1.x-style repository layout.
	 * 
	 * @parameter property="repositoryLayout" default-value="default"
	 */
	private String repositoryLayout;

	/**
	 * 
	 */
	public void execute() throws MojoExecutionException, MojoFailureException {

		getLog().info(
				"Scanning directory '" + unpacked.getAbsolutePath() + "' for distribution...");

		//for each jar in unpacked dir
		Collection<File> jars = FileUtils.listFiles(unpacked, new String[]{"jar"}, false);
		for (File jar : jars) {
			String base = FilenameUtils.getBaseName(jar.getName());
			deploy(jar, new File(unpacked, base + ".pom"));
		}
		Collection<File> poms = FileUtils.listFiles(unpacked, new String[]{"xml"}, false);
		for (File pom : poms) {
			String base = FilenameUtils.getBaseName(pom.getName());
			deploy(pom, pom);
		}
	}

	public void deploy(File file, File pom) throws MojoExecutionException, MojoFailureException {

		Model model = readModel(pom);
		validateArtifactInformation(model);

		String groupId = model.getGroupId();
		String artifactId = model.getArtifactId();
		String version = model.getVersion();
		String packaging = model.getPackaging();
		String classifier = null;

		Artifact artifact = artifactFactory.createArtifactWithClassifier(
				groupId, artifactId, version, packaging, classifier);

		if (! "pom".equals(packaging)) {
			ArtifactMetadata pomMetadata = new ProjectArtifactMetadata(artifact, pom);
			artifact.addMetadata(pomMetadata);
		}

		ArtifactRepositoryLayout layout = getLayout(repositoryLayout);

		ArtifactRepository deploymentRepository = repositoryFactory
				.createDeploymentArtifactRepository(repositoryId,
						repositoryUrl, layout, true);
		
		String protocol = deploymentRepository.getProtocol();
		if (StringUtils.isEmpty(protocol)) {
			throw new MojoExecutionException("No transfer protocol found.");
		}

		try {
			super.deploy(file, artifact, deploymentRepository, getLocalRepository());
		} catch (ArtifactDeploymentException e) {
			throw new MojoExecutionException("Error deploying file " + file.getName(), e);
		}
		
		String docs = model.getProperties().getProperty("javadoc", "spoon!");
		File javadoc = new File(unpacked, docs);
		if (javadoc.exists()) {
			artifact = artifactFactory.createArtifactWithClassifier(groupId, artifactId, version, "jar", "javadoc");
			try {
				super.deploy(javadoc, artifact, deploymentRepository, getLocalRepository());
			} catch (ArtifactDeploymentException e) {
				throw new MojoExecutionException("Error deploying API docs " + javadoc, e);
			}
		}
	}

	/**
	 * Parses a POM.
	 * 
	 * @param pomFile
	 *            The path of the POM file to parse, must not be
	 *            <code>null</code>.
	 * @return The model from the POM file, never <code>null</code>.
	 * @throws MojoExecutionException
	 *             If the POM could not be parsed.
	 */
	private Model readModel(File pomFile) throws MojoExecutionException {
		Reader reader = null;
		try {
			reader = ReaderFactory.newXmlReader(pomFile);
			return new MavenXpp3Reader().read(reader);
		} catch (FileNotFoundException e) {
			throw new MojoExecutionException("File not found " + pomFile, e);
		} catch (IOException e) {
			throw new MojoExecutionException("Error reading POM " + pomFile, e);
		} catch (XmlPullParserException e) {
			throw new MojoExecutionException("Error parsing POM " + pomFile, e);
		} finally {
			IOUtil.close(reader);
		}
	}

	/**
	 * Validates the user-supplied artifact information.
	 * 
	 * @throws MojoExecutionException
	 *             If any artifact coordinate is invalid.
	 */
	private void validateArtifactInformation(Model model)
			throws MojoExecutionException {

		ModelValidationResult result = modelValidator.validate(model);

		if (result.getMessageCount() > 0) {
			throw new MojoExecutionException(
					"The artifact information is incomplete or not valid:\n"
							+ result.render("  "));
		}
	}
}